package com.fzj.charging.device.dao.repository.impl;

import com.fzj.charging.device.dao.repository.StationRedisRepository;
import com.fzj.charging.device.pojo.entity.ChargingStation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@Repository("geoString")
public class StationRedisGeoAndStringRepositoryImpl implements StationRedisRepository {
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public void saveStationLocation(List<ChargingStation> chargingStationList) {
        HashMap<Integer, Point> stationLocationMap = new HashMap<>();
        HashMap<String, ChargingStation> stationInfoMap = new HashMap<>();
        if(chargingStationList!=null&&!chargingStationList.isEmpty()){
            for (ChargingStation chargingStation : chargingStationList) {
                BigDecimal stationLng = chargingStation.getStationLng();
                BigDecimal stationLat = chargingStation.getStationLat();
                Point point = new Point(new Double(String.valueOf(stationLng)), new Double(String.valueOf(stationLat)));
                stationLocationMap.put(chargingStation.getId(),point);
                stationInfoMap.put("station_info_"+chargingStation.getId(),chargingStation);
            }
        }
        String key = "station_geo";
        BoundGeoOperations geoOperations = redisTemplate.boundGeoOps(key);
        geoOperations.add(stationLocationMap);
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.multiSet(stationInfoMap);

    }

    @Override
    public List<ChargingStation> selectStation(Double lng, Double lat, Double distance) {
        Circle circle = getCircle(lng, lat, distance);
        ArrayList<ChargingStation> chargingStationList = new ArrayList<>();
        GeoResults<RedisGeoCommands.GeoLocation<Integer>> stationGeoResults = redisTemplate.boundGeoOps("station_geo").radius(circle);
        for (GeoResult<RedisGeoCommands.GeoLocation<Integer>> stationGeoResult : stationGeoResults) {
            RedisGeoCommands.GeoLocation<Integer> content = stationGeoResult.getContent();
            Integer stationId = content.getName();

            ValueOperations<String,ChargingStation> valueOperations = redisTemplate.opsForValue();
            ChargingStation chargingStation = valueOperations.get("station_info_" + stationId);
            chargingStationList.add(chargingStation);
        }
        return chargingStationList;
    }

    public Circle getCircle(Double lng,Double lat,Double distance){
        Point point = new Point(lng, lat);
        Distance geoDistance = new Distance(distance, Metrics.KILOMETERS);
        return new Circle(point,geoDistance);
    }
}
